﻿Imports System.IO
Imports System.Text.RegularExpressions
Imports System.Threading
Imports ajayumi.develop.VBasic.Core
Imports ajSerializer = ajayumi.develop.VBasic.Core.Xml.Serialization.Serializer

''' <summary>
''' 网络资源管理类
''' </summary>
''' <remarks></remarks>
Public Class WebResourceManager

#Region "Properties"


    'Private Shared m_Instance As WebResourceManager = Nothing
    'Public Shared ReadOnly Property Instance() As WebResourceManager
    '    Get
    '        Return m_Instance
    '    End Get
    'End Property

    Private m_TaskQueue As Queue(Of WebResourceInfo) = Nothing
    ''' <summary>
    ''' 任务队列
    ''' </summary>
    Public ReadOnly Property TaskQueue() As Queue(Of WebResourceInfo)
        Get
            Return m_TaskQueue
        End Get
    End Property


    Private m_HistoryList As List(Of WebResourceInfo)
    ''' <summary>
    ''' 历史列表
    ''' </summary>
    Public ReadOnly Property HistoryList() As List(Of WebResourceInfo)
        Get
            Return m_HistoryList
        End Get
    End Property

    Private m_Domain As String = String.Empty
    Public Property Domain() As String
        Get
            Return m_Domain
        End Get
        Set(ByVal value As String)
            m_Domain = value
        End Set
    End Property

    Private m_IsCancellation As Boolean = False
    Public ReadOnly Property IsCancellation() As Boolean
        Get
            Return m_IsCancellation
        End Get
    End Property


#End Region


    'Shared Sub New()
    '    m_Instance = New WebResourceManager()
    'End Sub

    Public Sub New()
        Me.m_HistoryList = New List(Of WebResourceInfo)()
        Me.m_TaskQueue = New Queue(Of WebResourceInfo)()
    End Sub

#Region "Events"

    ''' <summary>
    ''' 分析完数据后触发
    ''' </summary>
    ''' <remarks></remarks>
    Public Event AnaylzeCompleted As EventHandler(Of AnalyzeCompletedEventArgs)
    Public Overridable Sub OnAnalyzeCompleted(ByVal e As AnalyzeCompletedEventArgs)
        If e IsNot Nothing Then
            RaiseEvent AnaylzeCompleted(Me, e)
        End If
    End Sub

#End Region

#Region "private method"



    ''' <summary>
    ''' 判断是否存在
    ''' </summary>
    ''' <param name="url"></param>
    ''' <param name="resType"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function isExist(ByVal url As String, ByVal resType As ResourceType) As Boolean
        Dim _Result As Boolean = False
        Dim _ResourceInfos = From _ResourceInfo In Me.HistoryList _
                             Where _ResourceInfo.Url.Equals(url) And _ResourceInfo.ResourceType.Equals(resType) _
                             Select _ResourceInfo

        If _ResourceInfos.Count > 0 Then
            _Result = True
        End If

        Return _Result
    End Function

    ''' <summary>
    ''' 格式化保存文件的文件名
    ''' </summary>
    ''' <param name="dir">文件的完整路径</param>
    ''' <returns></returns>
    Private Function formatSaveFileName(ByVal dir As String) As String
        Dim _FileName As String = Regex.Replace(Me.Domain, "http://", String.Empty, RegexOptions.IgnoreCase)
        _FileName = _FileName.Replace("."c, "_"c)
        Return Path.Combine(dir, String.Format("addr({0}).xml", _FileName))
    End Function



    ''' <summary>
    ''' 获取网络资源
    ''' </summary>
    ''' <param name="url"></param>
    ''' <param name="htmlCode"></param>
    ''' <remarks></remarks>
    Private Sub getWebResources(url As String, htmlCode As String)
        Dim _ResList As List(Of WebResourceInfo) = Nothing

        _ResList = WebResourceService.GetResourcesList(url, htmlCode, ResourceType.Url)
        For Each item As WebResourceInfo In _ResList
            If isExist(item.Url, ResourceType.Url) = False Then
                Me.TaskQueue.Enqueue(item)
                Me.HistoryList.Add(item)
            End If
        Next

        _ResList = WebResourceService.GetResourcesList(url, htmlCode, ResourceType.Image)
        Dim _ImgResList As New List(Of WebResourceInfo)()
        For Each item As WebResourceInfo In _ResList
            If isExist(item.Url, ResourceType.Image) = False Then
                item.IsVisit = True
                Me.HistoryList.Add(item)
                _ImgResList.Add(item)
            End If
        Next

        Me.OnAnalyzeCompleted(New AnalyzeCompletedEventArgs(Nothing, _
                                                            Me.IsCancellation, _
                                                            url, _ImgResList, Me))
    End Sub

    ''' <summary>
    ''' 获取网络资源回调方法
    ''' </summary>
    ''' <param name="ar"></param>
    ''' <remarks></remarks>
    Private Sub getWebResources_Callback(ar As IAsyncResult)
        Dim _Handler As Action(Of String, String) = DirectCast(ar.AsyncState, Action(Of String, String))
        _Handler.EndInvoke(ar)
    End Sub

#End Region

#Region "public method"

    Public Sub Analyze(ByVal url As String, ByVal htmlCode As String)
        Dim _SiteUrl As String = WebResourceService.TrimSlash(url)

        If Me.isExist(_SiteUrl, ResourceType.Url) = False Then
            Dim _ResourceInfo As New WebResourceInfo() With {.Url = _SiteUrl, _
                                                          .ResourceType = ResourceType.Url, _
                                                          .IsVisit = True}
            Me.m_HistoryList.Add(_ResourceInfo)
        Else
            Dim _ResourceInfos = From _ResourceInfo In Me.HistoryList _
                                 Where _ResourceInfo.Url.Equals(_SiteUrl) And _ResourceInfo.ResourceType.Equals(ResourceType.Url) _
                                 Select _ResourceInfo
            For Each _ResourceInfo As WebResourceInfo In _ResourceInfos
                _ResourceInfo.IsVisit = True
            Next
        End If

        Dim _Handler As New Action(Of String, String)(AddressOf Me.getWebResources)
        _Handler.BeginInvoke(_SiteUrl, htmlCode, New AsyncCallback(AddressOf Me.getWebResources_Callback), _Handler)
    End Sub


    ''' <summary>
    ''' 从栈中获得链接字符串
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function [Next]() As String
        Dim _ResourceInfo As WebResourceInfo = Nothing
        If Me.m_TaskQueue.Count > 0 Then
            _ResourceInfo = Me.m_TaskQueue.Dequeue()
            While (String.IsNullOrEmpty(Me.Domain) = False AndAlso _
                   _ResourceInfo.Url.Contains(Me.Domain) = False AndAlso _
                   _ResourceInfo.IsVisit = False)
                If Me.m_TaskQueue.Count > 0 Then
                    _ResourceInfo = Me.m_TaskQueue.Dequeue()
                Else
                    Exit While
                End If
            End While
        End If

        Dim _url As String = String.Empty
        If _ResourceInfo IsNot Nothing Then
            _url = _ResourceInfo.Url
        End If

        Return _url
    End Function

    Public Sub ClearAll()
        Me.m_TaskQueue.Clear()
    End Sub

    ''' <summary>
    ''' 获得待访问站点的数量
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetTaskQueueCount() As Integer
        Return Me.m_TaskQueue.Count
    End Function

    ''' <summary>
    ''' 保存历史访问记录
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Save() As Boolean
        Dim _Result As Boolean = False

        Try
            If Me.m_HistoryList.Count > 0 Then
                Using _MemoryStream As MemoryStream = ajSerializer.SerializeXml(Of List(Of WebResourceInfo))(Me.m_HistoryList)

                    Dim _FilePath As String = Me.formatSaveFileName(AppDomain.CurrentDomain.BaseDirectory)

                    Dim _Byte() As Byte = _MemoryStream.ToArray()
                    Using _FileStream As New FileStream(_FilePath, FileMode.OpenOrCreate)
                        _FileStream.Write(_Byte, 0, _Byte.Length)
                    End Using

                End Using
            End If

            _Result = True
        Catch ex As Exception
            Throw ex
        End Try

        Return _Result
    End Function

    Public Function Load(ByVal filePath As String) As Boolean
        Dim _Result As Boolean = False

        Try
            If File.Exists(filePath) = False Then
                Return _Result
            End If

            Dim fileContents As Byte()
            fileContents = My.Computer.FileSystem.ReadAllBytes(filePath)
            Me.m_HistoryList = ajSerializer.DeSerializeFromXml(Of List(Of WebResourceInfo))(fileContents)

            Dim _ResourceInfos = From _ResourceInfo In Me.m_HistoryList _
                                 Where _ResourceInfo.ResourceType.Equals(ResourceType.Url) And _ResourceInfo.IsVisit = False _
                                 Select _ResourceInfo Distinct

            For Each _ResourceInfo As WebResourceInfo In _ResourceInfos
                Me.m_TaskQueue.Enqueue(_ResourceInfo)
            Next

            Dim _url As String = Me.Next()
            If String.IsNullOrEmpty(_url) = False Then
                _Result = True
                Me.OnAnalyzeCompleted(New AnalyzeCompletedEventArgs(Nothing, False, _url, New List(Of String), Me))
            End If
        Catch ex As Exception
            Throw ex
        End Try

        Return _Result
    End Function

    ''' <summary>
    ''' 从文件名中获取网站根地址
    ''' </summary>
    ''' <param name="filePath">文件的万盏地址</param>
    ''' <returns></returns>
    Public Function GetDomainFormFileName(ByVal filePath As String) As String
        Dim _Domain As String = Regex.Match(filePath, "addr\((?<url>.*)\)", RegexOptions.IgnoreCase).Groups("url").Value
        _Domain = _Domain.Replace("_"c, "."c)
        Return String.Concat("http://", _Domain)
    End Function

    Public Sub [Cancel]()
        Me.m_IsCancellation = True
    End Sub

    Sub [Continue]()
        Me.m_IsCancellation = False
        Me.OnAnalyzeCompleted(New AnalyzeCompletedEventArgs(Nothing, _
                                                            Me.IsCancellation, _
                                                            String.Empty, New List(Of WebResourceInfo)(), Me))
    End Sub

#End Region


End Class
